﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace App.Utility.Paging
{
    /// <summary>
    /// Contains filtering and sorting settings
    /// </summary>
    public class PagingSet
    {
        public ContractList<string> SortableFields { get; set; }
        public ContractList<string> FilterFields { get; set; }
        public ContractList<string> SortableFieldTypes { get; set; }
        public ContractList<string> FilterableFieldTypes { get; set; }
        public string SortByQueryStringParameterName { get; set; }
        public string DirectionQueryStringParameterName { get; set; }
        public string FilterByQueryStringParameterName { get; set; }
        public string FilterQueryStringParameterName { get; set; }
        public string ActionLinkFormatter { get; set; }
        public string FilterInputFormatter { get; set; }
        public string DefaultSortField { get; set; }
        public bool DefaultSortDirection { get; set; }
        public string FilterAllText { get; set; }

        public static PagingSet DefaultConfiguration()
        {
            return new PagingSet
            {
                ActionLinkFormatter = "<a href=\"{0}\">{1}</a>",
                FilterInputFormatter = @"<form action=""{0}"" method=""get""><input type=""text"" name=""{2}"" value=""{4}"" /> <input type=""submit"" value=""{1}"" /><br class=""clear"" />{5}{3}</form>",
                SortByQueryStringParameterName = "orderby",
                DirectionQueryStringParameterName = "asc",
                FilterByQueryStringParameterName = "filterby",
                FilterQueryStringParameterName = "expr",
                DefaultSortDirection = true,
                FilterAllText = "All"
            };
        }

        public PageRequest ParsePagingQueryStringToPageRequest(int? page, int PageSize, HttpContextBase HttpContext)
        {
            ContractList<Filter> filters= new ContractList<Filter>();
            ContractList<Sort> sorts=new ContractList<Sort>();
            int zIndex = (page ?? 1) - 1; ;

            if (!String.IsNullOrEmpty(HttpContext.Request.QueryString[SortByQueryStringParameterName]))
            {
                string matched = null; string sortBy = (string)HttpContext.Request.QueryString[SortByQueryStringParameterName];
                SortableFields.ForEach(s => { if (s.Equals(sortBy, StringComparison.OrdinalIgnoreCase)) matched = s; });
                if (matched != null)
                {
                    bool direction = true;
                    Boolean.TryParse(HttpContext.Request.QueryString[DirectionQueryStringParameterName], out direction);

                    sorts.Add(new Sort
                    {
                        Parameter = matched,
                        Ascending = direction,
                        TypeName = SortableFieldTypes[SortableFields.IndexOf(matched)]
                    });
                }
            }
            if (!String.IsNullOrEmpty(HttpContext.Request.QueryString[FilterByQueryStringParameterName]))
            {
                List<string> matches = MatchFiltersFromQueryString(HttpContext);

                if (matches.Count>0)
                {
                    string expression = Convert.ToString(HttpContext.Request.QueryString[FilterQueryStringParameterName]);
                    if (!String.IsNullOrEmpty(expression))
                    {
                        foreach (string match in matches)
                            filters.Add(new Filter
                            {
                                BinaryExpression = FilterBinaryExpression.Equal,
                                Parameter = match,
                                TypeName = FilterableFieldTypes[SortableFields.IndexOf(match)],
                                Value = expression
                            });
                    }
                }
            }

            if (sorts.Count == 0)
            {
                string matched = null; string sortBy = DefaultSortField;
                if (String.IsNullOrEmpty(sortBy))
                    sortBy = SortableFields[0];
                SortableFields.ForEach(s => { if (s.Equals(sortBy, StringComparison.OrdinalIgnoreCase)) matched = s; });
                if (matched != null)
                {
                    sorts.Add(new Sort
                    {
                        Parameter = matched,
                        Ascending = DefaultSortDirection,
                        TypeName = SortableFieldTypes[SortableFields.IndexOf(matched)]
                    });
                }
            }

            PageRequest pageRequest = new PageRequest(zIndex, PageSize, filters, sorts);
            pageRequest.FilterType = PageRequest.FilterTypes.Or;
            return pageRequest;
        }

        public List<string> MatchFiltersFromQueryString(HttpContextBase HttpContext)
        {
            List<string> matches = new List<string>(); 
            string filterBy = (string)HttpContext.Request.QueryString[FilterByQueryStringParameterName]??"";
            List<string> filterBys = new List<string>();

            if (filterBy.Contains(",")){
                filterBys = new List<string>(filterBy.Split(','));}
            else
                filterBys.Add(filterBy);

            filterBys.ForEach(f =>
            {
                FilterFields.ForEach(s =>
                {
                    if (s.Equals(f, StringComparison.OrdinalIgnoreCase))
                        if (!matches.Contains(s)) matches.Add(s);
                });
            });

            if (filterBys.Contains(FilterAllText))
                matches = FilterFields;
            return matches;
        }


    }
}
